#include <iostream>
#include <vector>
#include <typeinfo>

int f()
{
    return 10;
}

// int k(auto a)
// {
//     return 0;
// }

int main()
{
	// 规则1 如果初始化表达式是一个单值的基本类型（例如整数、浮点数、字符等），那么推导出的类型就是该基本类型。
    // auto的使用必须马上初始化，否则无法推导出类型
    // auto a; //编译错误 不符合规则1
    auto a = 10;    // 推导为int类型
    auto b = 3.14;  // 推导为double类型
    auto c = 'A';   // 推导为char类型

	std::cout << "a = " << a << std::endl;
    std::cout << "b = " << b << std::endl;
    std::cout << "c = " << c << std::endl;

	// 规则2 auto在一行定义多个变量时，各个变量的推导不能产生二义性，否则编译失败
    auto d = 1, e = 2; //正确
    // auto d = 1, e = 2, f = 's'; //编译错误，前面推导出的类型是int，c的类型是char。不符合规则2
    std::cout << "d = " << d << std::endl;
    std::cout << "e = " << e << std::endl;

    // 规则3 表达式推导：如果初始化表达式是一个复杂的表达式，那么推导出的类型就是表达式的结果类型。
    auto sum = 2 + 3.14;     // 推导为double类型
    auto result = f();    // 推导为f()返回值的类型

    std::cout << "sum = " << sum << std::endl;
    std::cout << "result = " << result << std::endl;

    //规则4 不能定义数组 可以定义指针,可以定义引用
    // auto a[2] = {1,2}; //错误 auto不能定义数组
    int k = 10;
    auto *p = &k; //正确 auto可以定义指针
    auto &pp = k;	//正确 auto可以定义引用

    std::cout << "p = " << *p << std::endl;
    std::cout << "pp = " << pp << std::endl;

    // 规则5 在不声明为引⽤或指针时，auto会忽略等号右边的引⽤类型的cv限定
    // cv限定是指：限定符是 const 和 volatile 关键字的统称。
    const int m = 10;
    auto n = m; //int 忽略const
    n = 20; //正确
    std::cout << "n = " << n << std::endl;

    //规则6 在声明为引⽤或者指针时，auto会保留等号右边的引⽤的cv限定
    const int h = 30;
    auto* p1 = &h;	//const int*
    // *p1 = 20; //错误
    std::cout << "p1 = " << *p1 << std::endl;

    const int g = 50;
	auto& p2 = g;	//const int&
    // p2 = 20; //错误 因为p2是const
    std::cout << "p2 = " << p2 << std::endl;

    // 规则7 auto被视作是一个占位符，并不是一个他自己的类型，因此不能用于类型转换或其他一些操作。比如sizeof
    int size = sizeof(int); //正确
    // int ssize = sizeof(auto); //错误，auto不是类型

    //规则 8 auto不能定义全局变量

    // 规则8 对于一些简单的变量类型来说，不建议使用auto，应该直接写出变量类型，这样更加清晰易懂。
    // auto适用于类型冗长复杂、使用范围专一的变量，如：
    std::vector<int> v;
    v.push_back(11);
    v.push_back(22);
	for (auto i = v.begin(); i < v.end(); i++)//i的类型为std::vector<int>::iterator
	{
		std::cout << *i << std::endl;
	}
    return 0;
}